﻿using System;
using System.Data;
using System.Configuration;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
using System.Collections.Generic;
using System.Xml;
using System.Text;
using System.Reflection;

///   <summary> 
///  实体转Xml，Xml转实体类
///   </summary> 
///   <typeparam name="T"></typeparam> 
public class XmlHelper<T> where T : new()
{
    #region  实体类转成Xml
    ///   <summary> 
    ///  对象实例转成xml
    ///   </summary> 
    ///   <param name="item"> 对象实例 </param> 
    ///   <returns></returns> 
    public static string EntityToXml(T item)
    {
        IList<T> items = new List<T>();
        items.Add(item);
        return EntityToXml(items);
    }

    ///   <summary> 
    ///  对象实例集转成xml
    ///   </summary> 
    ///   <param name="items"> 对象实例集 </param> 
    ///   <returns></returns> 
    public static string EntityToXml(IList<T> items)
    {
        // 创建 XmlDocument文档 
        XmlDocument doc = new XmlDocument();
        // 创建根元素 
        XmlElement root = doc.CreateElement(typeof(T).Name + " s ");
        // 添加根元素的子元素集 
        foreach (T item in items)
        {
            EntityToXml(doc, root, item);
        }
        // 向 XmlDocument文档添加根元素 
        doc.AppendChild(root);
        return doc.InnerXml;
    }

    private static void EntityToXml(XmlDocument doc, XmlElement root, T item)
    {
        // 创建元素 
        XmlElement xmlItem = doc.CreateElement(typeof(T).Name);
        // 对象的属性集 
        System.Reflection.PropertyInfo[] propertyInfo = typeof(T).GetProperties(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance);

        foreach (System.Reflection.PropertyInfo pinfo in propertyInfo)
        {
            if (pinfo != null)
            {
                // 对象属性名称 
                string name = pinfo.Name;
                // 对象属性值 
                string value = String.Empty;

                if (pinfo.GetValue(item, null) != null)
                    value = pinfo.GetValue(item, null).ToString(); // 获取对象属性值
                // 设置元素的属性值 
                xmlItem.SetAttribute(name, value);
            }
        }
        // 向根添加子元素 
        root.AppendChild(xmlItem);
    }


    #endregion

    #region  Xml转成实体类

    ///   <summary> 
    ///  Xml 转成对象实例
    ///   </summary> 
    ///   <param name="xml"> xml </param> 
    ///   <returns></returns> 
    public static T XmlToEntity(string xml)
    {
        IList<T> items = XmlToEntityList(xml);
        if (items != null && items.Count > 0)
            return items[0];
        else return default(T);
    }

    ///   <summary> 
    ///  Xml 转成对象实例集
    ///   </summary> 
    ///   <param name="xml"> xml </param> 
    ///   <returns></returns> 
    public static IList<T> XmlToEntityList(string xml)
    {
        XmlDocument doc = new XmlDocument();
        try
        {
            doc.LoadXml(xml);
        }
        catch
        {
            return null;
        }
        if (doc.ChildNodes.Count != 1)
            return null;
        if (doc.ChildNodes[0].Name.ToLower() != typeof(T).Name.ToLower() + " s ")
            return null;

        XmlNode node = doc.ChildNodes[0];

        IList<T> items = new List<T>();

        foreach (XmlNode child in node.ChildNodes)
        {
            if (child.Name.ToLower() == typeof(T).Name.ToLower())
                items.Add(XmlNodeToEntity(child));
        }

        return items;
    }

    private static T XmlNodeToEntity(XmlNode node)
    {
        T item = new T();

        if (node.NodeType == XmlNodeType.Element)
        {
            XmlElement element = (XmlElement)node;

            System.Reflection.PropertyInfo[] propertyInfo = typeof(T).GetProperties(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance);

            foreach (XmlAttribute attr in element.Attributes)
            {
                string attrName = attr.Name.ToLower();
                string attrValue = attr.Value.ToString();
                foreach (System.Reflection.PropertyInfo pinfo in propertyInfo)
                {
                    if (pinfo != null)
                    {
                        string name = pinfo.Name.ToLower();
                        Type dbType = pinfo.PropertyType;
                        if (name == attrName)
                        {
                            if (String.IsNullOrEmpty(attrValue))
                                continue;
                            switch (dbType.ToString())
                            {
                                case "System.Int32":
                                    pinfo.SetValue(item, Convert.ToInt32(attrValue), null);
                                    break;
                                case "System.Boolean":
                                    pinfo.SetValue(item, Convert.ToBoolean(attrValue), null);
                                    break;
                                case "System.DateTime":
                                    pinfo.SetValue(item, Convert.ToDateTime(attrValue), null);
                                    break;
                                case "System.Decimal":
                                    pinfo.SetValue(item, Convert.ToDecimal(attrValue), null);
                                    break;
                                case "System.Double":
                                    pinfo.SetValue(item, Convert.ToDouble(attrValue), null);
                                    break;
                                default:
                                    pinfo.SetValue(item, attrValue, null);
                                    break;
                            }
                            continue;
                        }
                    }
                }
            }
        }
        return item;
    }

    #endregion

    #region 其他写法，XML互操作
    /// <summary>
    ///  实体类序列化成xml
    /// </summary>
    /// <param name="enitities">The enitities.</param>
    /// <param name="headtag">The headtag.</param>
    /// <returns></returns>
    public static string ObjListToXml<T>(List<T> enitities, string headtag)
    {
        StringBuilder sb = new StringBuilder();
        PropertyInfo[] propinfos = null;
        sb.AppendLine("<?xml version=\"1.0\" encoding=\"utf-8\"?>");
        sb.AppendLine("<" + headtag + ">");
        foreach (T obj in enitities)
        {
            //初始化propertyinfo
            if (propinfos == null)
            {
                Type objtype = obj.GetType();
                propinfos = objtype.GetProperties();
            }
            sb.AppendLine("<item>");
            foreach (PropertyInfo propinfo in propinfos)
            {
                sb.Append("<");
                sb.Append(propinfo.Name);
                sb.Append(">");
                sb.Append(propinfo.GetValue(obj, null));
                sb.Append("</");
                sb.Append(propinfo.Name);
                sb.AppendLine(">");
            }
            sb.AppendLine("</item>");
        }
        sb.AppendLine("</" + headtag + ">");
        return sb.ToString();
    }
    /// <summary>
    ///  使用XML初始化实体类容器
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="typename">The typename.</param>
    /// <param name="xml">The XML.</param>
    /// <param name="headtag">The headtag.</param>
    /// <returns></returns>
    public static List<T> XmlToObjList<T>(XmlDocument doc, string headtag, XmlNamespaceManager nsmgr)
        where T : new()
    {
        List<T> list = new List<T>();
        PropertyInfo[] propinfos = null;
        XmlNodeList nodelist = doc.GetElementsByTagName(headtag);
        foreach (XmlNode node in nodelist)
        {
            T entity = new T();
            //初始化propertyinfo
            if (propinfos == null)
            {
                Type objtype = entity.GetType();
                propinfos = objtype.GetProperties();
            }
            //填充entity类的属性
            foreach (PropertyInfo propinfo in propinfos)
            {
                string v = GetNodeText(node, propinfo.Name);
                if (v != string.Empty)
                    propinfo.SetValue(entity, Convert.ChangeType(v, propinfo.PropertyType), null);
            }
            list.Add(entity);
        }
        return list;
    }

    public static string GetNodeText(XmlNode node, string matchName)
    {
        try
        {
            foreach (XmlNode childNode in node.ChildNodes)
            {
                if (childNode.LocalName.ToLower() == matchName.ToLower())
                { return childNode.InnerText; }
            }
        }
        catch { }
        return string.Empty;
    }
    #endregion

}
